/*
 * RealTimeClock.cpp
 *
 *  Created on: Jul 23, 2010
 *      Author: Wolfgang Klier
 */

#include "RealTimeClock.h"
#include "Wire.h"

#define DEFAULT_I2C_ADDRESS 0x68  // default I2C address for DS1307

// Convert the passed value to binary coded decimal
static uint8_t decToBcd(uint8_t num) {
  return ((num / 10) << 4) + num % 10;
}

// Convert the passed value from binary coded decimal
static uint8_t bcdToDec(uint8_t bcd) {
  return (bcd >> 4) * 10 + (bcd & 0xF);
}

RealTimeClock::RealTimeClock() : i2c_address_(-1) {}

void RealTimeClock::begin() {
  begin(DEFAULT_I2C_ADDRESS);
}

void RealTimeClock::begin(int i2c_address) {
  i2c_address_ = i2c_address;
}

struct tm RealTimeClock::getDate() {
  Wire.beginTransmission(i2c_address_);
  Wire.send(0);  // Set register pointer to 0
  Wire.endTransmission();

  struct tm date;
  Wire.requestFrom(i2c_address_, 7);
  date.tm_sec = bcdToDec(Wire.receive() & 0x7F);
  date.tm_min = bcdToDec(Wire.receive());
  date.tm_hour = bcdToDec(Wire.receive() & 0x3F);
  date.tm_wday = bcdToDec(Wire.receive());
  date.tm_mday = bcdToDec(Wire.receive());
  date.tm_mon = bcdToDec(Wire.receive());
  date.tm_year = bcdToDec(Wire.receive());
  return date;
}

void RealTimeClock::setDate(struct tm date) {
  Wire.beginTransmission(i2c_address_);
  Wire.send(0);  // Start register
  Wire.send(decToBcd(date.tm_sec) & 0x7F);
  Wire.send(decToBcd(date.tm_min));
  Wire.send(decToBcd(date.tm_hour));
  Wire.send(decToBcd(date.tm_wday));
  Wire.send(decToBcd(date.tm_mday));
  Wire.send(decToBcd(date.tm_mon));
  Wire.send(decToBcd(date.tm_year));
  Wire.endTransmission();
}

// Instance
RealTimeClock RTC = RealTimeClock();
